package boc.sx.gateway.util;

import boc.sx.gateway.core.strategy.LBStrategy;
import boc.sx.gateway.core.strategy.LBWay;
import boc.sx.gateway.core.strategy.LoadBalanceStrategy;
import boc.sx.gateway.service.BaseService;
import boc.sx.gateway.service.BusinessCode;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.BeansException;
import org.springframework.context.ApplicationContext;
import org.springframework.context.ApplicationContextAware;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.stereotype.Service;

import java.lang.annotation.Annotation;
import java.util.*;


@Configuration
@Slf4j
public class ApplicationContextUtil implements ApplicationContextAware {


    public static ApplicationContext applicationContext;


    /**
     * 查询是否包含该bean对象
     * @param beanName
     * @return
     */
    public static boolean containsBean(String beanName){return applicationContext.containsBean(beanName);}

    /**
     * 通过bean的id获取bean对象
     * @param beanName
     * @return
     */
    public static Object getBean(String beanName){
        return applicationContext.getBean(beanName);
    }
 
    /**
     * 根据bean的id和类型获取bean对象
     * @param beanName
     * @param clazz
     * @param <T>
     * @return
     */
    public static <T> T getBean(String beanName,Class<T> clazz){
        return clazz.cast(getBean(beanName));
    }
 
 
    @Override
    public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
        this.applicationContext = applicationContext;
    }


    @Bean("serviceMapping")
    public Map<String, BaseService> getServiceMapping(){
        Map<String, Object> beans = applicationContext.getBeansWithAnnotation(Service.class);
        Map<String,BaseService> classMap = new HashMap<>();
        for (Object value : beans.values()) {
            if(value instanceof Service){
                String serveCode = ((Service) value).value();
                classMap.put(serveCode,(BaseService)value);
            }
        }
        return classMap;
    }

    @Bean("lbStrategy")
    public HashMap<LBWay, LoadBalanceStrategy> getLBStrategy(){
        HashMap<LBWay, LoadBalanceStrategy> res = new HashMap<>();
        Map<String, Object> beans = applicationContext.getBeansWithAnnotation(LBStrategy.class);
        for (Object bean : beans.values()) {
            if(bean!=null){
                Annotation[] annotations = bean.getClass().getAnnotations();
                for (Annotation annotation:annotations){
                    if(annotation.annotationType() == LBStrategy.class && bean instanceof LoadBalanceStrategy){
                        LBStrategy anno = (LBStrategy) annotation;
                        res.put(LBWay.getLBWay(anno.value()),(LoadBalanceStrategy) bean);
                    }
                }
            }
        }
        log.info("================================= Scan Custom Annotation Successful ==========================================");
        return res;
    }

    public static HashMap<String,BaseService> getBusinessService(){
        HashMap<String, BaseService> res = new HashMap<>();
        Map<String, Object> beans = applicationContext.getBeansWithAnnotation(BusinessCode.class);
        for (Object bean : beans.values()) {
            if(bean!=null){
                Annotation[] annotations = bean.getClass().getAnnotations();
                for (Annotation annotation:annotations){
                    if(annotation.annotationType() == BusinessCode.class && bean instanceof BaseService){
                        BusinessCode anno = (BusinessCode) annotation;
                        res.put(anno.value(),(BaseService) bean);
                    }
                }
            }
        }
        return res;
    }
}